﻿using System;
using System.Linq;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using System.Windows.Forms;
using System.Collections.Generic;
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.SharePoint;
using Microsoft.VisualStudio.SharePoint.Deployment;
using Microsoft.VisualStudio.Shell.Flavor;
using CodeCounsel.SharePoint.DevTools.RegistrationAttributes;
using System.Reflection;
using Microsoft.VisualStudio.ExtensionManager;
using System.IO;
using System.Xml.Linq;

namespace CodeCounsel.SharePoint.DevTools
{
    [PackageRegistration(UseManagedResourcesOnly = true)]
    [DefaultRegistryRoot(@"Software\Microsoft\VisualStudio\10.0exp")]
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
    [Guid(VSPackageGuids.PackageText)]
    [ProvideMenuResource(1000, 1)]
    [ProvideAutoLoad(VSPackageGuids.UIContext_SharePointProject)]
    [ProvideComponentPickerPage(VSPackageGuids.SharePointReferencesPageText, VSPackageGuids.PackageText, "SharePoint")]
    public class VSPackage : Package, IVsComponentSelectorProvider
    {
        const string ExtensionIdentifier = "CodeCounsel.SharePoint.DevTools";

        List<MenuCommand> currentQuickDeployMenuCommands = new List<MenuCommand>();
        SharePointReferenceView control;

        SharePointReferenceView ReferenceViewControl
        {
            get
            {
                if (control == null)
                {
                    control = CreateSharePointReferenceView();
                }
                return control;
            }
        }

        protected override void Initialize()
        {
            ISharePointProjectService service = (ISharePointProjectService)GetService(typeof(ISharePointProjectService));
            OleMenuCommandService mcs = (OleMenuCommandService)GetService(typeof(IMenuCommandService));

            CommandID quickDeployCommandID = new CommandID(VSPackageGuids.CommandSet, VSPackageGuids.QuickDeployMenu);
            OleMenuCommand quickDeployCommand = new OleMenuCommand(delegate { }, quickDeployCommandID);
            quickDeployCommand.BeforeQueryStatus += delegate
            {
                IEnumerable<IVsHierarchy> selectedProjects = ProjectUtilities.GetSelectedProjects();
                IVsHierarchy projectHierarchy = selectedProjects.FirstOrDefault();
                quickDeployCommand.Visible = selectedProjects.Count() == 1 && ProjectUtilities.IsSharePointProject(projectHierarchy);
                if (quickDeployCommand.Visible)
                {
                    ClearQuickDeployMenu(mcs);
                    ISharePointProject project = service.Convert<IVsHierarchy, ISharePointProject>(projectHierarchy);
                    BuildQuickDeployMenu(mcs, project);
                }
            };
            mcs.AddCommand(quickDeployCommand);
            base.Initialize();
        }

        void ClearQuickDeployMenu(OleMenuCommandService mcs)
        {
            foreach (MenuCommand cmd in currentQuickDeployMenuCommands)
            {
                mcs.RemoveCommand(cmd);
            }
            currentQuickDeployMenuCommands.Clear();
        }

        void BuildQuickDeployMenu(OleMenuCommandService mcs, ISharePointProject project)
        {
            int commandIDCounter = 0;
            foreach (var deploymentConfig in project.DeploymentConfigurations)
            {
                OleMenuCommand deploymentCommand = CreateQuickDeploymentCommand(
                    commandIDCounter, deploymentConfig, project);
                mcs.AddCommand(deploymentCommand);
                currentQuickDeployMenuCommands.Add(deploymentCommand);
                commandIDCounter++;
            }
        }

        OleMenuCommand CreateQuickDeploymentCommand(
            int commandIDCounter,
            KeyValuePair<string, IDeploymentConfiguration> deploymentConfig,
            ISharePointProject project)
        {
            CommandID deploymentCommandID = new CommandID(VSPackageGuids.CommandSet, VSPackageGuids.QuickDeployButton + commandIDCounter);
            OleMenuCommand deploymentCommand = new OleMenuCommand(
                delegate
                {
                    project.ActiveDeploymentConfiguration = deploymentConfig.Key;
                    DTE _dte = ProjectUtilities.GetDTE();
                    _dte.ExecuteCommand("Build.DeploySelection");
                },
                deploymentCommandID);
            deploymentCommand.Text = deploymentConfig.Value.Name;
            return deploymentCommand;
        }

        int IVsComponentSelectorProvider.GetComponentSelectorPage(
            ref Guid rguidPage, VSPROPSHEETPAGE[] ppage)
        {
            if (rguidPage != VSPackageGuids.SharePointReferencesPage)
            {
                throw new ArgumentException("rguidPage");
            }
            ppage[0].dwSize = (uint)Marshal.SizeOf(typeof(VSPROPSHEETPAGE));
            ppage[0].hwndDlg = ReferenceViewControl.Handle;

            ppage[0].dwFlags = 0;
            ppage[0].HINSTANCE = 0;
            ppage[0].dwTemplateSize = 0;
            ppage[0].pTemplate = IntPtr.Zero;
            ppage[0].pfnDlgProc = IntPtr.Zero;
            ppage[0].lParam = IntPtr.Zero;
            ppage[0].pfnCallback = IntPtr.Zero;
            ppage[0].pcRefParent = IntPtr.Zero;
            ppage[0].dwReserved = 0;
            ppage[0].wTemplateId = (ushort)0;
            return VSConstants.S_OK;
        }

        SharePointReferenceView CreateSharePointReferenceView()
        {
            SharePointReferenceView view = new SharePointReferenceView();
            IVsExtensionManager extensionManager = (IVsExtensionManager)Package.GetGlobalService(typeof(SVsExtensionManager));
            IInstalledExtension extension = extensionManager.GetInstalledExtension(ExtensionIdentifier);
            string referenceXmlPath = Path.Combine(extension.InstallPath, "SharePointReferences.xml");
            view.ReferencePath = referenceXmlPath; 
            return view;
        }
    }
}